package cn.net.xyan.blossom.webUI.ui

import cn.net.xyan.blossom.kotlin.logger
import cn.net.xyan.blossom.webUI.utils.notification
import com.github.vok.karibudsl.*
import com.vaadin.annotations.Theme
import com.vaadin.annotations.Viewport
import com.vaadin.icons.VaadinIcons
import com.vaadin.navigator.Navigator
import com.vaadin.navigator.View
import com.vaadin.navigator.ViewChangeListener
import com.vaadin.navigator.ViewDisplay
import com.vaadin.server.ClassResource
import com.vaadin.server.Resource
import com.vaadin.server.VaadinRequest
import com.vaadin.shared.Version
import com.vaadin.spring.annotation.SpringUI
import com.vaadin.spring.annotation.SpringView
import com.vaadin.spring.navigator.SpringViewProvider
import com.vaadin.ui.CssLayout
import com.vaadin.ui.Notification
import com.vaadin.ui.UI
import com.vaadin.ui.VerticalLayout
import org.springframework.beans.factory.annotation.Autowired
import kotlin.reflect.KProperty
import kotlin.reflect.full.declaredMemberProperties
import kotlin.reflect.jvm.isAccessible

fun ValoMenu.menuButton(caption: String, viewName: String?, icon: Resource = VaadinIcons.MENU, badge: String? = null, block: MenuButton.()->Unit = {}): MenuButton {

    val menuButton = MenuButton()

    val properties = this::class.declaredMemberProperties.filter {
        it.name == "navigationButtonLayout"
    }
    if(properties.isNotEmpty()){
        val first: KProperty<Any?> = properties.first()
        first.isAccessible = true
        val cssLayout: CssLayout =  first.call(this) as CssLayout
        if (cssLayout!= null)
            cssLayout.addComponent(menuButton)

    }

    menuButton.icon = icon
    menuButton.badge = badge
    menuButton.caption = caption
    if (viewName != null) {
        menuButton.onLeftClick {
            // hides the menu on mobile phones, so that the user can see the outcome of the navigation without having
            // menu blocking the screen. This does nothing on desktop browsers.
            //menu.removeStyleName("valo-menu-visible")
            //navigateToView(view)
            this.ui.navigator.navigateTo(viewName)
        }
        //views[view] = this
    }
    menuButton.block()

    return menuButton
}


@SpringView(name = "")
class WelcomeView: VerticalLayout(), View {

    init {
        isMargin = true
        //title("Welcome To The Karibu-DSL Demo")

        label {
            w = fillParent
            html("""Karibu-DSL offers the following:
            <ul><li>Provides Vaadin DSL builder support, allowing you to build your Vaadin UIs in Kotlin declarative, statically compiler-checked code</li>
            <li>Provides auto-discovery of your Views</li></ul>
            And more.<br/><br/>You can find the sources of this app here: <a href='https://github.com/mvysny/karibu-dsl/tree/master/example-v8'>example-v8</a>""")
        }
        label {
            w = fillParent
            html("""<strong>Vaadin version:</strong> ${Version.getFullVersion()}<br/><strong>Kotlin version:</strong> ${KotlinVersion.CURRENT}<br/><strong>JVM version:</strong> $jvmVersion""")
        }
    }

    override fun enter(event: ViewChangeListener.ViewChangeEvent?) {
    }
}


@SpringUI(path = "/")
@Theme("blossom")
@Viewport("width=device-width, initial-scale=1.0")
class AdminUI : UI() {

    @Autowired
    lateinit var viewProvider: SpringViewProvider

    override fun init(request: VaadinRequest?) {
        val content = valoMenu {
            appTitle = "<h3><strong>系统管理</strong></h3>"
            userMenu {
                item("John Doe", ClassResource("/profilepic300px.jpg")) {
                    item("Edit Profile")
                    item("Preferences")
                    addSeparator()
                    item("Sign Out")
                }
            }

            viewProvider.viewNamesForCurrentUI.forEach {
                val title =  if (it != "") it  else "Home"
                menuButton(title,it)
            }

        }

        navigator = Navigator(this, content as ViewDisplay)
        navigator.addProvider(viewProvider)

        setErrorHandler { e ->
            logger.error("Vaadin UI uncaught exception ${e.throwable}", e.throwable)
            // when the exception occurs, show a nice notification
            "An error occurred, and we are really sorry about that. Already working on the fix!".notification("错误",Notification.Type.ERROR_MESSAGE)

        }
    }

}